/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.gui.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.*;

import nfse.gui.record.IPLinkFactory;
import nfse.gui.client.data.SensorTypes;
import nfse.gui.client.data.*;
import nfse.gui.client.data.SnapShotDataTypeCategoryRecord;

import com.gwtext.client.core.EventObject;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.HTMLPanel;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.TabPanel;
import com.gwtext.client.widgets.event.TabPanelListenerAdapter;
import com.gwtext.client.widgets.layout.HorizontalLayout;
import com.gwtext.client.widgets.layout.VerticalLayout;
import com.gwtext.client.widgets.menu.BaseItem;
import com.gwtext.client.widgets.menu.Item;
import com.gwtext.client.widgets.menu.Menu;
import com.gwtext.client.widgets.menu.event.BaseItemListenerAdapter;

public class SnapShotPanel extends Panel {
	private TabPanel tabPanel;
	private Panel verticalPanel;
	private Menu menu;
	private HashMap snapShotDataMap;
	private HashMap sensorTabsMap = new HashMap();
	private int rotationalViewIndex = 0;
	private String[] sensorTabOrder;
	private int width = 0;
	private int height = 0;

	private Panel targetPanel = null;
	private HeadsUpTab headsUpTab;

	public SnapShotPanel(int height, int width) {
		this.width = width;
		this.height = height;
	}

	public SnapShotPanel(HashMap snapShotDataMap, HeadsUpTab headsUpTab) {
		this.headsUpTab = headsUpTab;
		this.snapShotDataMap = snapShotDataMap;
	}

	public void testClass() {
		// This just tests that something can be displayed in the panel
		this.setHtml("Hello John");
	}

	public void refreshTabs(SnapShotData snapShotData) {

		snapShotDataMap = snapShotData.getSnapShotMap();

		verticalPanel.setTitle("Snap Shot Time Interval: Start: "
				+ snapShotData.getMinTime() + " End: "
				+ snapShotData.getMaxTime());

		String title = tabPanel.getActiveTab().getTitle();

		// Don't remove all of the tabs because the panel will not redraw
		// properly if it
		// is not accessed before and new rotation happens
		// So delete all but the one. There will be at least two tabs one for
		// the rotational view
		// and one for the single sensor. Anything less means that no sensors
		// are set up.
		Component[] items = tabPanel.getItems();
		for (int i = 1; i < items.length; i++) {
			Component component = items[i];
			tabPanel.remove(component);
		}

		String key = snapShotDataMap.keySet().iterator().next().toString();

		SensorTypes st = (SensorTypes) headsUpTab.getSensorTypesMap().get(key);
		String sensorName = st.getTypeName();

		Panel targetPanel = new Panel();

		if ((snapShotDataMap != null) && (snapShotDataMap.get(key) != null)) {
			targetPanel = addTab("Rotational View -  " + sensorName,
					(HashMap) snapShotDataMap.get(key));
		}

		
		tabPanel.add(targetPanel);
		sensorTabsMap.put("Rotational View", targetPanel);

		// This is a little convoluted. There has to be at least one tab in the
		// panel so as not to loose the
		// dimensions of the panel. Added a new rotational tab as the second tab
		// and then deleted the
		// first tab so the rotational tab in the second tab position now
		// becomes the first position
		items = tabPanel.getItems();
		if (items[0] != null)
			tabPanel.remove(items[0]);

		sensorTabOrder = new String[snapShotDataMap.size()];
		int q = 0;
		Iterator ssdmIt = snapShotDataMap.keySet().iterator();
		while (ssdmIt.hasNext()) {

			String dataType = (String) ssdmIt.next();
			sensorTabOrder[q++] = dataType;
			HashMap snapShotDataTypeMap = (HashMap) snapShotDataMap
					.get(dataType);

			st = (SensorTypes) headsUpTab.getSensorTypesMap().get(dataType);
			sensorName = st.getTypeName();

			Panel tab = new Panel();
			if (snapShotDataTypeMap != null)
				tab = addTab(sensorName, snapShotDataTypeMap);
			tabPanel.add(tab);
			sensorTabsMap.put(dataType, tab);
		}

		if (title.indexOf("Rot") != -1)
			tabPanel.activate(0);
		else {
			HashMap localSensorsMap = headsUpTab.getSensorTypesMap();
			int z = 0;
			Iterator it = localSensorsMap.keySet().iterator();
			while (it.hasNext()) {
				SensorTypes sType = (SensorTypes) localSensorsMap
						.get((String) it.next());
				if (sType.getTypeName().equals(title))
					tabPanel.activate(z + 1);
				z++;
			}
		}
	}

	public void getNewRotationalView() {
		try {
			if (tabPanel.getActiveTab() == null)
				tabPanel.activate(0);

			// This means that the headsup tab has not been visited. Any call to
			// activate a tab will not take effect until the tab is visited. So
			// getting the title will not work.
			// Since the user has not been to headsup tab at this point the
			// rotation does not matter.
			if (tabPanel.getActiveTab() == null)
				return;

			String title = tabPanel.getActiveTab().getTitle();

			if (rotationalViewIndex >= headsUpTab.getSensorTypesMap().size())
				rotationalViewIndex = 0;

			String dataTypeId = sensorTabOrder[rotationalViewIndex];
			String sensorName = (String) ((SensorTypes) headsUpTab
					.getSensorTypesMap().get(dataTypeId)).getTypeName();
			if (snapShotDataMap != null
					&& snapShotDataMap.get(dataTypeId) != null)
				targetPanel = (Panel) addTab("Rotational View - " + sensorName,
						(HashMap) snapShotDataMap.get(dataTypeId));

			tabPanel.activate(0);

			Component[] items = tabPanel.getItems();
			for (int i = 0; i < items.length; i++) {
				Component component = items[i];
				if (component.getId().equals(tabPanel.getActiveTab().getId())) {
					tabPanel.remove(component);
					break;
				}
			}
			tabPanel.insert(0, targetPanel);
			if (title.indexOf("Rot") != -1)
				tabPanel.activate(0);
			else {
				HashMap localSensorsMap = headsUpTab.getSensorTypesMap();
				int q = 0;
				Iterator it = localSensorsMap.keySet().iterator();
				while (it.hasNext()) {
					SensorTypes sType = (SensorTypes) localSensorsMap
							.get((String) it.next());
					if (sType.getTypeName().equals(title))
						tabPanel.activate(q + 1);
					q++;
				}
			}
			rotationalViewIndex++;
		} catch (Exception ex) {
			System.out.println("Failed in here with " + ex.getMessage());
			ex.printStackTrace();
		}
	}

	public void buildSnapShotTabPanel(SnapShotData snapShotData,
			HeadsUpTab headsUpTab) {
		this.headsUpTab = headsUpTab;
		this.snapShotDataMap = snapShotData.getSnapShotMap();
		this.setBorder(false);
		// this.setPaddings(15);
		verticalPanel = new Panel();
		verticalPanel.setLayout(new VerticalLayout(15));

		tabPanel = new TabPanel();
		tabPanel.setResizeTabs(true);
		// tabPanel.setMinTabWidth(115);
		tabPanel.setTabWidth(170);
		tabPanel.setAutoWidth(true);
		tabPanel.setEnableTabScroll(true);
		tabPanel.setHeight(425);
		tabPanel.setActiveTab(0);

		// tabPanel.addListener(new TabPanelListenerAdapter() {
		// public void onContextMenu(TabPanel source, Panel tab, EventObject e)
		// {
		// showMenu(tab, e);
		// }
		// });

		if (snapShotDataMap != null && snapShotDataMap.size() > 0) {
			// Get the first snapShot in the snapShotDataMap;
			String key = snapShotDataMap.keySet().iterator().next().toString();

			SensorTypes st = (SensorTypes) headsUpTab.getSensorTypesMap().get(
					key);
			String sensorName = st.getTypeName();

			Panel targetPanel = new Panel();

			if ((snapShotDataMap != null) && (snapShotDataMap.get(key) != null)) {
				targetPanel = addTab("Rotational View - " + sensorName,
						(HashMap) snapShotDataMap.get(key));
			}

			tabPanel.add(targetPanel);
			sensorTabsMap.put("Rotational View", targetPanel);

			sensorTabOrder = new String[snapShotDataMap.size()];
			int q = 0;
			Iterator ssdmIt = snapShotDataMap.keySet().iterator();
			while (ssdmIt.hasNext()) {

				String dataType = (String) ssdmIt.next();
				sensorTabOrder[q++] = dataType;
				HashMap snapShotDataTypeMap = (HashMap) snapShotDataMap
						.get(dataType);

				st = (SensorTypes) headsUpTab.getSensorTypesMap().get(dataType);
				sensorName = st.getTypeName();

				Panel tab = new Panel();
				if (snapShotDataTypeMap != null)
					tab = addTab(sensorName, snapShotDataTypeMap);
				tabPanel.add(tab);
				sensorTabsMap.put(dataType, tab);
			}

		} // End if snapShotDataMap != null && snapShotDataMap.size() > 0)
		else {
			tabPanel.setHtml("There is no data for this time period");
		}
		verticalPanel.add(tabPanel);
		verticalPanel.setTitle("Snap Shot Time Interval: Start: "
				+ snapShotData.getMinTime() + " End: "
				+ snapShotData.getMaxTime());

		this.add(verticalPanel);
	}

	private void showMenu(final Panel tab, EventObject e) {
		if (menu == null) {
			menu = new Menu();
			Item close = new Item("Close Tab");
			close.setId("close-tab-item");
			close.addListener(new BaseItemListenerAdapter() {
				public void onClick(BaseItem item, EventObject e) {
					tabPanel.remove(tabPanel.getActiveTab());
				}
			});
			menu.addItem(close);

			Item closeOthers = new Item("Close Other Tabs");
			closeOthers.setId("close-others-item");
			closeOthers.addListener(new BaseItemListenerAdapter() {
				public void onClick(BaseItem item, EventObject e) {
					Component[] items = tabPanel.getItems();
					for (int i = 0; i < items.length; i++) {
						Component component = items[i];
						if (!component.getId().equals(
								tabPanel.getActiveTab().getId())) {
							tabPanel.remove(component);
						}
					}
				}
			});
			menu.addItem(closeOthers);
		}

		BaseItem closeOthers = menu.getItem("close-others-item");
		if (tabPanel.getItems().length == 1) {
			closeOthers.disable();
		} else {
			closeOthers.enable();
		}
		menu.showAt(e.getXY());
	}

	public Panel addTab(String dataType, HashMap snapShotDataTypeMap) {

		String[] snapShotHeaders = { "Top Sources", "Top Targets", "Top Ports" };

		Panel tab = new Panel();
		// tab.setAutoScroll(true);

		tab.setTitle(dataType);
		// tab.setWidth(900);
		tab.setAutoWidth(true);
		tab.setHeight(400);
		// tab.setIconCls("tab-icon");
		if (snapShotDataTypeMap.size() > 0)
			tab.setLayout(new com.gwtext.client.widgets.layout.TableLayout(
					snapShotDataTypeMap.size()));

		for (int j = 0; j < snapShotDataTypeMap.size(); j++) {
			Panel localPanel = new Panel();
			// localPanel.setLayout(new
			// com.gwtext.client.widgets.layout.TableLayout(1));
			localPanel
					.setLayout(new com.gwtext.client.widgets.layout.VerticalLayout());
			localPanel.setTitle(snapShotHeaders[j]);
			localPanel.setAutoScroll(true);
			localPanel.setHeight(400);
			localPanel.setPaddings(5);
			int firstLine = 0;

			ArrayList categoryRecords = (ArrayList) snapShotDataTypeMap
					.get(snapShotHeaders[j]);
			Collections.sort(categoryRecords, new HitComparator());

			if (categoryRecords == null)
				continue;
			Iterator catIt = categoryRecords.iterator();

			int maxHit = 100;

			while (catIt.hasNext()) {
				SnapShotDataTypeCategoryRecord ssRecord = (SnapShotDataTypeCategoryRecord) catIt
						.next();

				// Column Headers (Address Hits or Port Hits)
				if (firstLine == 0) {
					// Compute Max hit
					maxHit = Math.round(new Float(ssRecord.getHits())
							.floatValue());

					Panel linePanel = new Panel();
					linePanel.setLayout(new HorizontalLayout(5));
					if (ssRecord.getAddress() != null) {
						HTMLPanel hPanel = new HTMLPanel();
						hPanel.setWidth(100);
						hPanel.setHtml("<center>Address</center>");
						hPanel.setStyle("font-size: 8pt;");
						linePanel.add(hPanel);
					} else {
						HTMLPanel hPanel = new HTMLPanel();
						hPanel.setWidth(100);
						hPanel.setHtml("<center>Port</center>");
						hPanel.setStyle("font-size: 8pt;");
						linePanel.add(hPanel);
					}

					HTMLPanel hPanel = new HTMLPanel();
					hPanel.setWidth(100);
					hPanel.setHtml("<center>Hits</center>");
					hPanel.setStyle("font-size: 8pt;");
					linePanel.add(hPanel);
					localPanel.add(linePanel);
					firstLine++;
				}

				String ip = ssRecord.getAddress();
				if (ip != null) {
					Panel linePanel = new Panel();
					linePanel.setLayout(new HorizontalLayout(5));
					IPLinkFactory ipf = new IPLinkFactory();
					String url = ipf.getURL(ip);
					String address = createTextHTML("<a target=\"_netfse_ip\" href=\"" + url + "\">" + ip + "</a>");
					String hits = createBarGraphHTML(ssRecord.getHits(), maxHit);
					linePanel.add(new HTMLPanel(address));
					linePanel.add(new HTMLPanel(hits));
					localPanel.add(linePanel);
				} else if (ssRecord.getPort() != null) {
					Panel linePanel = new Panel();
					linePanel.setLayout(new HorizontalLayout(5));
					String port = createTextHTML(ssRecord.getPort());
					String hits = createBarGraphHTML(ssRecord.getHits(), maxHit);
					linePanel.add(new HTMLPanel(port));
					linePanel.add(new HTMLPanel(hits));
					localPanel.add(linePanel);
				}

			} // End while (catIt.hasNext()) Populates the category of a Data
				// Type (Top Sources is a category)

			if (localPanel != null) {
				localPanel.setWidth(332);
				tab.add(localPanel);
			}

		} // for (int j = 0; j < snapShotDataTypeMap.size(); j++) Populates the
			// DataType Table . There can be n categories per Data Type Table

		return tab;
	}

	private String createBarGraphHTML(String rawData, int maxHit) {
		float temp = (new Float(rawData).floatValue()) / maxHit;
		int barGraphPercent = (int) (temp * 100);
		return "<div class='graph'> <strong class='bar' style='width:"
				+ barGraphPercent + "%;'><span>" + rawData
				+ "</span></strong></div>";

	}

	private String createTextHTML(String rawData) {
		return "<div class='non-graph-text' style='text-align:right' ><strong class='bar' > <span>"
				+ rawData + "</span></strong></div>";
		// return "<div class='non-graph-text' style='text-align:right'> <span>"
		// + rawData + "</span></div>";
	}

	public HashMap getSensorTabsMap() {
		return sensorTabsMap;
	}

	public void setSensorTabsMap(HashMap sensorTabsMap) {
		this.sensorTabsMap = sensorTabsMap;
	}

	public HashMap getSnapShotDataMap() {
		return snapShotDataMap;
	}

	public void setSnapShotDataMap(HashMap snapShotDataMap) {
		this.snapShotDataMap = snapShotDataMap;
	}

	class HitComparator implements Comparator {
		public int compare(Object o1, Object o2) {
			SnapShotDataTypeCategoryRecord ssData1 = (SnapShotDataTypeCategoryRecord) o1;
			SnapShotDataTypeCategoryRecord ssData2 = (SnapShotDataTypeCategoryRecord) o2;

			int s1 = new Integer(ssData1.getHits()).intValue();
			int s2 = new Integer(ssData2.getHits()).intValue();
			if (s1 < s2)
				return 1;
			else if (s1 == s2)
				return 0;
			else
				return -1;
		}
	}

	public TabPanel getTabPanel() {
		return tabPanel;
	}

	public void setTabPanel(TabPanel tabPanel) {
		this.tabPanel = tabPanel;
	}

}
